#ifndef GAMELOC_H
#define GAMELOC_H

#include <QMainWindow>
#include <QLabel>
#include <QFileSystemModel>
#include <QAbstractItemModel>
#include <QTimer>
#include <QSettings>

#include "ui_mainwindow.h"
#include "newfiledialog.h"
#include "progressdialog.h"
#include "addbuttondialog.h"
#include "editfolderproperties_dialog.h"
#include "editfileproperties_dialog.h"
#include "advancedsearchparamsdialog.h"
#include "glr.h"
#include "exportdialog.h"

namespace Ui {
class MainWindow;
}

class Gameloc : public QMainWindow
{    
    Q_OBJECT

protected:
    QString version;     // Версия программы
    QString programPath; // Путь к программе

    bool os_windows;    // Определение операционной системы
    // События
    void closeEvent(QCloseEvent *event);

    // Настройки
    QString userName;   // Имя пользователя

    // Диалоги
    Ui::MainWindow              *ui;
    NewFileDialog               *newFileDialog;
    ProgressDialog              *progressDialog;
    AddButtonDialog             *addButtonDialog;
    editFolderProperties_dialog *editFolderPropsDialog;
    EditFileProperties_Dialog   *editFilePropertiesDialog;
    AdvancedSearchParamsDialog  *advancedSearchParamsDialog;
    ExportDialog                *exportDialog;

    // Сохранение файла
    QVector <Folder*>   save_folder;        // Массив родительских папок записываемого файла
    QVector <int>       save_folderIndex;   // Массив индексов папок. Используется для перехода от папки к папке. Последний индекс соответствует последней папке
    QVector <int>       save_soundIndex;    // Массив индексов файлов папок. Индекс относится к той папке, к которой относятся и остальные два массива

    int                 save_tabs;          // Количество табуляций перед строкой в info.dat
    int                 save_counter;       // Счетчик записаных файлов, для того чтобы знать когда заканчивать цикл

    // Создание нового проекта
    QStringList *cnf_fileTree;        // Дерево файлов
    QString     *cnf_path2orig;       // Путь к оригинальной озвучке
    QString     *cnf_path2temp;       // Путь ко временной папке
    QString     *cnf_path2copySounds; // Путь к папке для копирования звуков во временной папке
    int         *cnf_treeIndex;       // Индекс следующего файла (копирование, создание папок)
    int          cnf_tabs;            // Количество табуляций перед данными в info.dat

    QStringList *cnf_prevPath;      // Генерация info файла: Предыдущий путь
    QStringList *cnf_curPath;       // Генерация info файла: Текущий путь

    bool        cnf_isSubDir;       // Генерация info файла: Текущая папка это поддиректория предыдущей?
    bool        cnf_mainInfoWriten; // Генерация info файла: Записана ли основная информация

    // Архивация
    QString     *arc_path;      // Путь для сохранения архива

    QProcess    *arc_7zr;

    // Открытие файла GLR
    void openFromTempPath(QString tempPath, bool fromGLR); // Открыть проект из временной папки

    QVector <GLR*> openedFiles;     // Открытые в программе проекты

    QString *archiveToExtract;          // Открываемый файл GLR

    // Закрытие программы
    int close_index;
    bool close_allSaved;
    bool close_yesToAll;
    bool close_noToAll;

    // Поиск файлов
    QList <int> search_subdirIndexes;
    Folder*     search_curFolder;

    QString     search_partOfFilename;
    QString     search_partOfCommentary;
    QStringList search_tagList;

    int         search_fileIndex;

    bool        search_somethingWasFounded;

    bool        searchNext_mode;

    QVector <GLR*> unsavedFiles;

    // Инициализация программы
    void setup_FileTree_and_folderTree_ContextMenu();
    void setup_toolBar();

    // Прочие необходимые переменные\функции
    QString     getFileNameFromPath( QString path);
    QStringList getFolderTree(QString dir);     // Получение дерева папок заданной папки
    QStringList getFileTree  (QString dir);     // Получение дерева файлов заданной папки

    QStringList getFileParentDirs(QString path);    // Получение имен родительских папок файла

    void writeWithTabs(int tabs, QString text);     // Функция для записи в info файл (на который ссылается QFile* infoFile)
                                                    // строки с заданным количеством табуляций

    void setPlayerAvailable(bool available);    // Устанавливает группу элементов UI плеера активными или неактивными

    SoundFile* activeSound;     // Активный звук (Нужен для определения выбранной переозвучки для работы с ней)
    GLR*       activeGLR;       // Активный GLR  (Нужен для определения GLR, из которого нужно брать данные при сохранении)

    QString gameloc_tempFolders_path; // Путь к папке, в которой создаются временные папки проектов

    QFile*  infoFile;           // Общая переменная указывающая на info файлы, используемые при сохранении/создании нового/открытии проекта

    QTimer *t;
    QTimer *playTimer;
    QTimer *update_window_size_timer; // Таймер используется для постоянного обновления ширины столбцов таблиц при изменениях

    QString pathToLastAddedRevoice;    // Последний путь используемый при добавлении переозвучки

    // Воспроизведение/Запись файлов
    Audio *playerAndRecorder;     // Более приятная и простая морда скрывающая весь код для работы с QAudio и BASS

    // Настройки программы
    QSettings   *settings;    // Собственно настройки
    QStringList recentFiles; // Список последних открытых файлов

    void readSettings();    // Прочитать настройки
    void writeSettings();   // Записать настройки
    void addRecentFile();   // Добавить к последним открытым файл

    // Контекстное меню /////////////////////////
    // FolderTree. Дерево папок
    QAction* folderTree_changeProperties_action;    // Изменить свойства папки (иконка, комментарий, тег)
    QAction* folderTree_closeActivePrj_action;      // Закрыть активный проект
    QAction* folderTree_showStatistic_action;       // Показать статистику текущего проекта (сколько переведено, сколько не переведено, в процентах, последний редактируемый файл)

    QAction* folderTree_clearAction;
    QMenu  * folderTree_clearMenu;             // Меню очистки
    QAction* folderTree_clearAll_action;       // Очистить звук от вариантов перевода и текста перевода
    QAction* folderTree_clearRevoices_action;  // Очистить звук от вариантов перевода
    QAction* folderTree_clearText_action;      // Очистить звук от текста перевода

    // FileTree. Список файлов
    QAction* fileTree_clearAction;
    QMenu  * fileTree_clearMenu;                // Меню очистки
    QAction* fileTree_clearAll_action;          // Очистить звук от вариантов перевода и текста перевода
    QAction* fileTree_clearRevoices_action;     // Очистить звук от вариантов перевода
    QAction* fileTree_clearText_action;         // Очистить звук от текста перевода
    QAction* fileTree_changeProperties_action;  // Изменить свойства (комментарий, тег)

    // ToolBar ///////////////////////
    // Поиск файлов
    QLineEdit* searchField;
    QAction*   searchAction;
    QAction*   advancedSearchParamsAction;

    // Подзаголовочное меню ////////////
    // Экспорт
    QString     exportPath;
    bool        mainFiles;

    QList <int> export_subdirIndexes;
    Folder*     export_curFolder;
    int         export_fileIndex;


public:
    Gameloc(bool weHaveArgument, QString fileToOpen, QWidget *parent = 0);

public slots:
    /* ------ Основные действия------ */

    // Слоты для обработки основных действий пользователя (сохранение, открытие, создание...)
    void on_playButton_toggled( bool checked );  // Если нажата кнопка воспроизведения
    void on_stopButton_clicked();                // Если нажата кнопка остановки
    void on_saveAction_triggered();              // Если выбран пункт меню "Сохранить"
    void on_saveAsAction_triggered();            // Если выбран пункт меню "Сохранить как"
    void openProjectFromFile();       // Если выбран пункт меню "Открыть другой файл"
    void on_newFileAction_triggered();           // Если выбран пункт меню "Новый файл"

    // Создание нового проекта
    void cnf_start();                         // Получение дерева, вывод диалога progressDialog
    void cnf_createFolders();                 // Создание папок во временной папке
    void cnf_copyFiles();                     // Копирование файлов
    void cnf_generateInfo();                  // Генерация info.dat
    void cnf_generateInfo_writeFolder(QString name); // Запись информации о текущей папке
    void cnf_generateInfo_writeFile(int index);  // Запись информации о текущем файле
    void cnf_end();

    // Сохранение открытого проекта
    void save_start();                           // Подготовка к генерации info-файла
    void save_generateInfo();                                 // Собственно генерация info-файла
    void save_generateInfo_writeFolders(int tabs, Folder *curFolder);  // Запись информации о папках
    void updateProgressWhileArchivating();

    // Открытие файла
    void extractArchiveOnOpen();
    void openRecentFile();  // Открыть выбранный из последних открытых файл

    void updateProgressWhileExtracting();
    // Архивация
    void arc_start();
    void arc_archivating();

    // Добавление кнопки программы
    void on_addButton_clicked();

    // Закрытие программы
    void onClose();

    // Экспорт
    void prepareTo_ExportToFolder();
    void exportToFolder_start(QString exportPath, bool mainFiles);
    void exportToFolder_cycle();

    /*
    void prepareToExportToArchive();
    void exportToArchive();
    */

    /* --- Редактирование GLR --- */
    void cellEdited( int row, int column);

    void on_translateTextChanged();     // Записать в activeSound текст перевода при его вводе
    void addRevoiceFromFolder();          // Добавить файл переозвучки с компьютера
    void deleteRevoice();
    void recordNewRevoice(bool start);
    void rerecordRevoice(bool start);

    void clearFolder_texts()        { clearFolder(false, true); }
    void clearFolder_revoices()     { clearFolder(true, false); }
    void clearFolder_all()          { clearFolder(true, true);  }
    void clearFolder(bool revoices, bool texts);

    void clearSound_text();
    void clearSound_revoices();
    void clearSound_all();

    /* ------ Прочие вспомогательные слоты ------ */

    void reopenRevoice();

    // Дают указателям на активные объекты ссылки на активные объекты
    void setActiveSound(QTreeWidgetItem* n_activeSound);
    void setActiveGLR(QTreeWidgetItem* newActiveGLR);

    void on_playEnded() { ui->playButton->setChecked(false); disconnect(t, SIGNAL(timeout()), this, SLOT(updateWidgets_onPlay()));}

    // Правильная работа морды
    void loadRevoiceOnSelect(int row);  // Определяет выбранный вариант переозвучки и загружает её в AUD

    void updateWidgets_onPlay();    // Обновление лейбла и слайдера показывающих позицию воспроизведения
    void clearRevoiceTable();       // Очистка таблицы вариантов переозвучки при выборе другой папки
    void updateRevoicesTable_on_currentSoundChanged(QTreeWidgetItem* newItem);
    void updateTablesViewOnResize();
    void updateRecentFileActions();
    void clearRecentFileList();

    void checkAvailabilityOfSearchRequest();

    // Конекстное меню
    void on_editFolderProperties();
    void on_folderTree_currentItemChanged(QTreeWidgetItem* current);

    void editSoundProperties();

    // Поиск
    void on_advancedSearchParamsAction_triggered();
    void search_fromMainWindow();

    void search_start( QString partOfFilename, QString partOfCommentary, QStringList tags );
    void search_continue();
    void search();

    SoundFile* searchInCurFolder();
    bool search_compareStrings( QString searchRequest, QString string);

    void searchTextChanged();

    QString readStyleSheet(QString fileName);
    void on_updateStyleSheetAction_triggered() { setStyleSheet( readStyleSheet(":/themes/dark_orange_metal/dark_orange_metal.qss")); }

signals:
    void saved();
};

#endif // GAMELOC_H
